home *** CD-ROM | disk | FTP | other *** search
/ Software of the Month Club 1996 April / Software of the Month Club 1996 April.iso / pc / os2 / psutils / src / psutil.c < prev    next >
C/C++ Source or Header  |  1996-02-21  |  9KB  |  336 lines

  1. /* psutil.c
  2.  * Copyright (C) Angus J. C. Duggan 1991-1995
  3.  * See file LICENSE for details.
  4.  *
  5.  * utilities for PS programs
  6.  */
  7.  
  8. /*
  9.  *  AJCD 6/4/93
  10.  *    Changed to using ftell() and fseek() only (no length calculations)
  11.  *  Hunter Goatley    31-MAY-1993 23:33
  12.  *    Fixed VMS support.
  13.  *  Hunter Goatley     2-MAR-1993 14:41
  14.  *    Added VMS support.
  15.  */
  16. #include "psutil.h"
  17. #include "pserror.h"
  18. #include "patchlev.h"
  19.  
  20. #include <string.h>
  21. #include <sys/types.h>
  22. #include <sys/stat.h>
  23.  
  24. #define iscomment(x,y) (strncmp(x,y,strlen(y)) == 0)
  25.  
  26. extern char *program ;
  27. extern int pages;
  28. extern int verbose;
  29. extern FILE *infile;
  30. extern FILE *outfile;
  31. extern char pagelabel[BUFSIZ];
  32. extern int pageno;
  33.  
  34. static char buffer[BUFSIZ];
  35. static long bytes = 0;
  36. static long pagescmt = 0;
  37. static long headerpos = 0;
  38. static long endsetup = 0;
  39. static long beginprocset = 0;        /* start of pstops procset */
  40. static long endprocset = 0;
  41. static int outputpage = 0;
  42. static int maxpages = 100;
  43. static long *pageptr;
  44.  
  45. /* list of paper sizes supported */
  46. static Paper papersizes[] = {
  47.    { "a3", 842, 1191 },        /* 29.7cm * 42cm */
  48.    { "a4", 595, 842 },        /* 21cm * 29.7cm */
  49.    { "a5", 421, 595 },        /* 14.85cm * 21cm */
  50.    { "b5", 516, 729 },        /* 18.2cm * 25.72cm */
  51.    { "A3", 842, 1191 },        /* 29.7cm * 42cm */
  52.    { "A4", 595, 842 },        /* 21cm * 29.7cm */
  53.    { "A5", 421, 595 },        /* 14.85cm * 21cm */
  54.    { "B5", 516, 729 },        /* 18.2cm * 25.72cm */
  55.    { "letter", 612, 792 },    /* 8.5in * 11in */
  56.    { "legal", 612, 1008 },    /* 8.5in * 14in */
  57.    { "ledger", 1224, 792 },    /* 17in * 11in */
  58.    { "tabloid", 792, 1224 },    /* 11in * 17in */
  59.    { "statement", 396, 612 },    /* 5.5in * 8.5in */
  60.    { "executive", 540, 720 },    /* 7.6in * 10in */
  61.    { "folio", 612, 936 },    /* 8.5in * 13in */
  62.    { "quarto", 610, 780 },    /* 8.5in * 10.83in */
  63.    { "10x14", 720, 1008 },    /* 10in * 14in */
  64.    { NULL, 0, 0 }
  65. };
  66.  
  67. /* return pointer to paper size struct or NULL */
  68. Paper* findpaper(char *name)
  69. {
  70.    Paper *pp;
  71.    for (pp = papersizes; PaperName(pp); pp++) {
  72.       if (strcmp(PaperName(pp), name) == 0) {
  73.      return pp;
  74.       }
  75.    }
  76.    return (Paper *)NULL;
  77. }
  78.  
  79. /* make a file seekable; trick stolen from Chris Torek's libdvi */
  80. FILE *seekable(FILE *fp)
  81. {
  82.    FILE *ft;
  83.    long r, w;
  84.    char *p;
  85. #if defined(WINNT)
  86.    struct _stat fs ;
  87. #endif
  88.  
  89. #if defined(WINNT)
  90.    if (_fstat(fileno(fp), &fs) == 0 && (fs.st_mode&_S_IFREG) != 0)
  91.      return (fp);
  92. #else
  93.    if (!fseek(fp, 0L, SEEK_CUR))
  94.      return (fp);
  95. #endif
  96.  
  97. #if defined(MSDOS)
  98.    message(FATAL, "input is not seekable\n");
  99.    return (NULL) ;
  100. #else
  101.    if ((ft = tmpfile()) == NULL)
  102.      return (NULL);
  103.  
  104.    while ((r = fread(p = buffer, sizeof(char), BUFSIZ, fp)) > 0) {
  105.       do {
  106.     if ((w = fwrite(p, sizeof(char), r, ft)) == 0)
  107.       return (NULL) ;
  108.     p += w ;
  109.     r -= w ;
  110.       } while (r > 0) ;
  111.    }
  112.  
  113.    if (!feof(fp))
  114.      return (NULL) ;
  115.  
  116.    /* discard the input file, and rewind the temporary */
  117.    (void) fclose(fp);
  118.    if (fseek(ft, 0L, SEEK_SET) != 0)
  119.      return (NULL) ;
  120.  
  121.    return (ft);
  122. #endif
  123. }
  124.  
  125.  
  126. /* copy input file from current position upto new position to output file */
  127. static int fcopy(long upto)
  128. {
  129.    long here = ftell(infile);
  130.    while (here < upto) {
  131.       if ((fgets(buffer, BUFSIZ, infile) == NULL) ||
  132.       (fputs(buffer, outfile) == EOF))
  133.      return(0);
  134.       here = ftell(infile);
  135.       bytes += strlen(buffer);
  136.    }
  137.    return (1);
  138. }
  139.  
  140. /* build array of pointers to start/end of pages */
  141. void scanpages(void)
  142. {
  143.    register char *comment = buffer+2;
  144.    register int nesting = 0;
  145.    register long int record;
  146.  
  147.    if ((pageptr = (long *)malloc(sizeof(long)*maxpages)) == NULL)
  148.       message(FATAL, "out of memory\n");
  149.    pages = 0;
  150.    fseek(infile, 0L, SEEK_SET);
  151.    while (record = ftell(infile), fgets(buffer, BUFSIZ, infile) != NULL)
  152.       if (*buffer == '%') {
  153.      if (buffer[1] == '%') {
  154.         if (nesting == 0 && iscomment(comment, "Page:")) {
  155.            if (pages >= maxpages-1) {
  156.           maxpages *= 2;
  157.           if ((pageptr = (long *)realloc((char *)pageptr,
  158.                          sizeof(long)*maxpages)) == NULL)
  159.              message(FATAL, "out of memory\n");
  160.            }
  161.            pageptr[pages++] = record;
  162.         } else if (headerpos == 0 && iscomment(comment, "Pages:"))
  163.            pagescmt = record;
  164.         else if (headerpos == 0 && iscomment(comment, "EndComments"))
  165.            headerpos = ftell(infile);
  166.         else if (iscomment(comment, "BeginDocument") ||
  167.              iscomment(comment, "BeginBinary") ||
  168.              iscomment(comment, "BeginFile"))
  169.            nesting++;
  170.         else if (iscomment(comment, "EndDocument") ||
  171.              iscomment(comment, "EndBinary") ||
  172.              iscomment(comment, "EndFile"))
  173.            nesting--;
  174.         else if (nesting == 0 && iscomment(comment, "EndSetup"))
  175.            endsetup = record;
  176.         else if (nesting == 0 &&
  177.                iscomment(comment, "BeginProcSet: PStoPS"))
  178.            beginprocset = record;
  179.         else if (beginprocset && !endprocset &&
  180.              iscomment(comment, "EndProcSet"))
  181.            endprocset = ftell(infile);
  182.         else if (nesting == 0 && iscomment(comment, "Trailer")) {
  183.            fseek(infile, record, SEEK_SET);
  184.            break;
  185.         }
  186.      } else if (headerpos == 0 && buffer[1] != '!')
  187.         headerpos = record;
  188.       } else if (headerpos == 0)
  189.      headerpos = record;
  190.    pageptr[pages] = ftell(infile);
  191.    if (endsetup == 0 || endsetup > pageptr[0])
  192.       endsetup = pageptr[0];
  193. }
  194.  
  195. /* seek a particular page */
  196. void seekpage(int p)
  197. {
  198.    fseek(infile, pageptr[p], SEEK_SET);
  199.    if (fgets(buffer, BUFSIZ, infile) != NULL &&
  200.        iscomment(buffer, "%%Page:")) {
  201.       char *start, *end;
  202.       for (start = buffer+7; isspace(*start); start++);
  203.       if (*start == '(') {
  204.      int paren = 1;
  205.      for (end = start+1; paren > 0; end++)
  206.         switch (*end) {
  207.         case '\0':
  208.            message(FATAL, "Bad page label while seeking page %d\n", p);
  209.         case '(':
  210.            paren++;
  211.            break;
  212.         case ')':
  213.            paren--;
  214.            break;
  215.         }
  216.       } else
  217.      for (end = start; !isspace(*end); end++);
  218.       strncpy(pagelabel, start, end-start);
  219.       pagelabel[end-start] = '\0';
  220.       pageno = atoi(end);
  221.    } else
  222.       message(FATAL, "I/O error seeking page %d\n", p);
  223. }
  224.  
  225. /* Output routines. These all update the global variable bytes with the number
  226.  * of bytes written */
  227. void writestring(char *s)
  228. {
  229.    fputs(s, outfile);
  230.    bytes += strlen(s);
  231. }
  232.  
  233. /* write page comment */
  234. void writepageheader(char *label, int page)
  235. {
  236.    if (verbose)
  237.       message(LOG, "[%d] ", page);
  238.    sprintf(buffer, "%%%%Page: %s %d\n", label, ++outputpage);
  239.    writestring(buffer);
  240. }
  241.  
  242. /* search for page setup */
  243. void writepagesetup(void)
  244. {
  245.    char buffer[BUFSIZ];
  246.    if (beginprocset) {
  247.       for (;;) {
  248.      if (fgets(buffer, BUFSIZ, infile) == NULL)
  249.         message(FATAL, "I/O error reading page setup %d\n", outputpage);
  250.      if (!strncmp(buffer, "PStoPSxform", 11))
  251.         break;
  252.      if (fputs(buffer, outfile) == EOF)
  253.         message(FATAL, "I/O error writing page setup %d\n", outputpage);
  254.      bytes += strlen(buffer);
  255.       }
  256.    }
  257. }
  258.  
  259. /* write the body of a page */
  260. void writepagebody(int p)
  261. {
  262.    if (!fcopy(pageptr[p+1]))
  263.       message(FATAL, "I/O error writing page %d\n", outputpage);
  264. }
  265.  
  266. /* write a whole page */
  267. void writepage(int p)
  268. {
  269.    seekpage(p);
  270.    writepageheader(pagelabel, p+1);
  271.    writepagebody(p);
  272. }
  273.  
  274. /* write from start of file to end of header comments */
  275. void writeheader(int p)
  276. {
  277.    fseek(infile, 0L, SEEK_SET);
  278.    if (pagescmt) {
  279.       if (!fcopy(pagescmt) || fgets(buffer, BUFSIZ, infile) == NULL)
  280.      message(FATAL, "I/O error in header\n");
  281.       sprintf(buffer, "%%%%Pages: %d 0\n", p);
  282.       writestring(buffer);
  283.    }
  284.    if (!fcopy(headerpos))
  285.       message(FATAL, "I/O error in header\n");
  286. }
  287.  
  288. /* write prologue to end of setup section excluding PStoPS procset */
  289. int writepartprolog(void)
  290. {
  291.    if (beginprocset && !fcopy(beginprocset))
  292.       message(FATAL, "I/O error in prologue\n");
  293.    if (endprocset)
  294.       fseek(infile, endprocset, SEEK_SET);
  295.    writeprolog();
  296.    return !beginprocset;
  297. }
  298.  
  299. /* write prologue up to end of setup section */
  300. void writeprolog(void)
  301. {
  302.    if (!fcopy(endsetup))
  303.       message(FATAL, "I/O error in prologue\n");
  304. }
  305.  
  306. /* write from end of setup to start of pages */
  307. void writesetup(void)
  308. {
  309.    if (!fcopy(pageptr[0]))
  310.       message(FATAL, "I/O error in prologue\n");
  311. }
  312.  
  313. /* write trailer */
  314. void writetrailer(void)
  315. {
  316.    fseek(infile, pageptr[pages], SEEK_SET);
  317.    while (fgets(buffer, BUFSIZ, infile) != NULL) {
  318.       writestring(buffer);
  319.    }
  320.    if (verbose)
  321.       message(LOG, "Wrote %d pages, %ld bytes\n", outputpage, bytes);
  322. }
  323.  
  324. /* write a page with nothing on it */
  325. void writeemptypage(void)
  326. {
  327.    if (verbose)
  328.       message(LOG, "[*] ");
  329.    sprintf(buffer, "%%%%Page: * %d\n", ++outputpage);
  330.    writestring(buffer);
  331.    if (beginprocset)
  332.       writestring("PStoPSxform concat\n");
  333.    writestring("showpage\n");
  334. }
  335.  
  336.